#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "FS.h"
#include <ESP8266mDNS.h>
#include <ArduinoJson.h>
#include <LittleFS.h>
//#include <Ticker.h>
#ifndef AP_SSID
#define AP_SSID "guiyn-wifi-timer"
#define AP_PSK  "11111111"
#endif
#include <TimeLib.h>

IPAddress AP_LOCAL_IP(192, 168, 10, 1); //手动设置的开启的网络的ip地址
IPAddress AP_GATEWAY(192, 168, 10, 1); //手动设置的网关IP地址
IPAddress AP_SUBNET(255, 255, 255, 0); //手动设置的子网掩码



ESP8266WebServer server(80);


//Ticker ticker; 用了timelib 后ticker 就不好使了功能放到了loop里面

const String SETTING_FILE_NAME = "/timer_set.html";
const String TIMER_CONF_FILE_NAME = "/timer_conf.json";

// 常量
const String TIMER_JSON_CONF_KEY_CYCLE_MIN = "CYCLE_MIN";
const String TIMER_JSON_CONF_KEY_WAIT_MIN = "WAIT_MIN";
const String TIMER_JSON_CONF_KEY_RUN_MIN = "RUN_MIN";
const String TIMER_JSON_CONF_KEY_BEGIN_HOUR = "BEGIN_HOUR";
const String TIMER_JSON_CONF_KEY_END_HOUR = "END_HOUR";
const int TICKER_TIME = 30;
String SETTING_HTML;

//配置周期默认值
int cn_val = 120;
int wmn_val = 0;
int rmn_val = 10;
int bhn_val = 9;
int ehn_val = 18;

//引脚定义 
int output_pin = D6;
int input_button = D7;
int input_ctrl = D5;

//计数器
long counter = 0;
int currenter = 0;


String timer_status;


// web 服务设置
void webServerSetting() {

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }

  server.on("/", settingRoot);
  server.on("/ts",  timerSetter);
  server.on("/status",  timerSataus);
  server.onNotFound(notFound);
  server.begin();


  SETTING_HTML  = loadFile(SETTING_FILE_NAME);
  Serial.println("HTTP server started");
}
void notFound( ) {
  server.send(404, "text/html", "not found");
}
void settingRoot( )
{
  server.send(200, "text/html", SETTING_HTML);
}

void timerSataus( )
{
  String mess = "run:" + String(rmn_val) + "\n sleep:" + String(cn_val) + "\n current:" + String(currenter) + "\n count:" + String(counter) + "\n status:" + timer_status;
  server.send(200, "text/html", mess);
}
// 设置请求servlet
void timerSetter( )
{
  Serial.println("get timer set request ..");
  String s_ch, s_cm, s_cn, s_wmn, s_rmn, s_bhn, s_ehn;
  s_ch = server.arg("ch");
  s_cm = server.arg("cm");
  s_cn = server.arg("cn");
  s_wmn = server.arg("wmn");
  s_rmn = server.arg("rmn");
  s_bhn = server.arg("bhn");
  s_ehn = server.arg("ehn");
  Serial.println("cur hour " + s_ch);
  Serial.println("cur min  " + s_cm);
  Serial.println("cycle min time " + s_cn);
  Serial.println("wait min num " + s_wmn);
  Serial.println("run min num" + s_rmn);
  Serial.println("begin hour num " + s_bhn);
  Serial.println("end hour num " + s_ehn);
  int ch_val = atoi(s_ch.c_str());
  int cm_val = atoi(s_cm.c_str());
  int nowtime = ch_val * 60 + cm_val;
  Serial.println("local now time >" + String(nowtime));
  setTime(ch_val, cm_val, 0, 1, 1, 2000);
  Serial.println("local time hour >" + hour());
  cn_val = atoi(s_cn.c_str()) * 2;
  wmn_val = atoi(s_wmn.c_str()) * 2;
  rmn_val = atoi(s_rmn.c_str()) * 2;
  bhn_val = atoi(s_bhn.c_str()) ;
  ehn_val = atoi(s_ehn.c_str()) ;
  saveJsonConf();
  String mess =  s_ch + ":" + s_cm + "\n" + s_cn + " >> " + s_wmn + " >> " + s_rmn + " \n " +
                 s_bhn + " >> " + s_ehn
                 + " \n " + "setting success..";
  server.send(200, "text/html", mess);
}


void setup(void) {

  pinMode(output_pin, OUTPUT);
  pinMode(input_button, INPUT);
  pinMode(input_ctrl, INPUT);
  digitalWrite(output_pin, LOW);
  Serial.begin(115200);
  
  delay(500);
  if (!SPIFFS.begin()) {
    Serial.println("open SPIFFS error..");
    return;
  }
  else {
    Serial.println("open SPIFFS success..");
    loadConf();
  }
  delay(500);
  WiFi.softAPConfig (AP_LOCAL_IP, AP_GATEWAY, AP_SUBNET);
  WiFi.softAP(AP_SSID, AP_PSK);
  Serial.println("WIFI AP MODEL START ..");
  webServerSetting();
//  sleep_val = cn_val - rmn_val;
  //ticker.attach(TICKER_TIME, doTicker);
}

// 状态记录对象
unsigned long buttonClickWait = 0;
int buttonState = 0;
unsigned int APS_flag = 0;
long apCheck = 0;
long tickerCheck = 0;

void loop(void) {
  server.handleClient();
  unsigned  long currentMillis = millis();

  // 按钮长按两秒 打开AP模式
  buttonState = digitalRead(input_button);
  if (buttonState == HIGH)
  {
    buttonClickWait++;
  }
  else
  {
    buttonClickWait = 0;
  }

  if (buttonClickWait > 2000 && buttonClickWait < 2100)
  {
    // open ap Model

    // set ap led high
    buttonClickWait = 0;
  }

  // 30秒一次的ticker
  if ((currentMillis - tickerCheck) > 29999)
  {
    tickerCheck = currentMillis;
    doTicker();
  }

  // AP 模式检查,两秒一次。无连接1分钟后关闭
  if (WiFi.softAPIP() && (currentMillis - apCheck) > 2000 )
  {
    apCheck = currentMillis;
    //      Serial.println("APS_flag..."+String(APS_flag));
    checkAPServer();
  }
}
int AP_IDLE_NUM = 0;

// 检查AP 启动模式
void  checkAPServer() {

  // 判断是否有连接 自动进行关闭AP 服务
  if ( WiFi.softAPgetStationNum() < 1)
  {
    Serial.println("当前服务无连接..." + String(AP_IDLE_NUM));
    AP_IDLE_NUM++;
    // 连续间隔30次没有访问 直接关闭AP 服务
    if (AP_IDLE_NUM > 30)
    {
      Serial.println("do Ap Server close ..");
      WiFi.softAPdisconnect(true);//关闭接入点
      Serial.println("Ap Server close..");
      AP_IDLE_NUM = 0;
    }
  }
  else {
    Serial.printf("连接此接入点上的无线终端数目 = %d\n", WiFi.softAPgetStationNum());
    AP_IDLE_NUM = 0;
  }

}



int counter_flag = 0;
void doTicker() {

  //运行时间范围内。
  int _hh = hour();
  Serial.println(">>" + String(_hh) + ">>" + String(bhn_val) + ">>" + String(ehn_val));
  if (_hh < bhn_val || _hh >= ehn_val )
  {
    return;
  }

  // 起始等待时间
  if (wmn_val > 0)
  {
    wmn_val = wmn_val - 1;
    return;
  }
  // 运行循环定时任务

  currenter = currenter + 1;
  if (currenter > 0 && currenter <=  rmn_val)
  {
    counter_flag = counter_flag + 1;
    if (counter_flag == rmn_val)
    {
      counter = counter + 1;
      counter_flag = 0;
    }
    timer_status = "working ......";
    digitalWrite(output_pin, HIGH);
  }
  else if (currenter > rmn_val  && currenter < cn_val)
  {
    timer_status = "sleeping ......";
    digitalWrite(output_pin, LOW);
  }
  else
  {
    timer_status = "resetting ......";
    digitalWrite(output_pin, LOW);
    currenter = 0;
  }

  String mess = "run:" + String(rmn_val) + "\n cycle:" + String(cn_val) + "\n current:" + String(currenter) + "\n count:" + String(counter) + "\n status:" + timer_status;
  
  Serial.println(mess);


}
